// 代理沙箱

// defaultValue 只代理用户设置的值，不代理window对象上原生的元素和方法，比如：location和addEventListener 还是在原生的 window 对象上去执行
let defaultValue = {}; // 子应用的沙箱容器，之后我们子应用对于window上所有的属性操作都放在 defaultValue 上这个对象上
export class ProxySandbox{
  constructor(){
    this.proxy = null;
    this.active();
  }
  // 沙箱激活
  active(){
    // 使用 Proxy 这样一个 api 来实现我们的沙箱的功能
    // Proxy 可以将它所代理的对象做一个拦截，我们之后对它代理对象所作的任何操作都会在它的拦截函数里执行一次
    // 如果说我们子应用需要设置属性，那么这个时候不希望它将属性直接设置在 window 上而是设置在我们一个容器里面这个容器呢我们将暂存子应用所有的设置的值，这时候呢我们首先创建一个全局的对象
    this.proxy = new Proxy(window, {
      get(target, key){
        // 也就是说我们当前对于window上的get和set的操作都已经跳过了window这个对象而是直接将它赋值在了defaultValue里面
        if(typeof target[key] === 'function'){
          return target[key].bind(target); // 针对于window.addEventListener这种是一个方法，并且在 defaultValue 这个代理对象上是无法去处理的
        } // 不执行这个会提示 `TypeError：Illegal invocation`
        return defaultValue[key] || target[key]; // 如果在 defaultValue 上的没有找到值，就去原来的 window 对象上查找（比如：location 对象就要到 window 对象上去找）
      },
      // target 就是我们代理的 window
      set(target, key, value){
        defaultValue[key] = value;
        return true; // return true 设置成功
      }
    });
  }
  // 沙箱销毁
  inactive(){
    defaultValue = {};
  }
}

